﻿using Hue_Demo_PCL.Models;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;

namespace Hue_Demo_PCL.Services
{
    public class HueService
    {
        // the username requested by the user
        private string userName = "";
        // If the requested username is not available, the Hue api will
        //   offer a GUID username, which we will store in verifiedUser
        private string verifiedUser = "";

        // use this url to get the hue ip
        //   http://www.meethue.com/api/nupnp
        //  or open up router admin panel.
        //  You may need to look up at http://192.168.1.1
        //  and look for the Philips Hue in the attached devices and 
        //  copy the IP address into the bridgeIP string
        
        private string bridgeIP = "192.168.1.2";
        
        public HueSettings Hub;
        private string returnedUser;

        public HueService() { }
        public HueService(HueSettings hub) {
            Hub = hub;
        }

        // Ping the bridge, see if it exists
        public async Task<bool> IsBridgeAvailable()
        {
            var httpClient = new HttpClient();
            var hueUri = new Uri(string.Format("http://{0}/api/{1}", bridgeIP, userName));

            var response = await httpClient.GetAsync(hueUri);
            string returnString = "";
            try
            {
                returnString = await response.Content.ReadAsStringAsync();
                if (returnString != null && returnString.Length > 5)
                    return true;
                else return false;
            }
            catch (Exception ex)
            {
                return false;
            }
        }

        // Set up the user (either create or verify)
        public async Task<string> SetupUser(string savedUser, bool isNew)
        {
            userName = savedUser;
            string returnString = savedUser;
            if (isNew)
                returnString = await SetupUser();
            return returnString;
        }

        // Set up the user (create)
        public async Task<string> SetupUser()
        {
            try 
            {
                var httpClient = new HttpClient();
                // Create new registration object in JSON
                var reg = new
                {
                    username = userName,
                    devicetype = "DemoProject"
                };

                var jsonObj = JsonConvert.SerializeObject(reg);

                var response = await httpClient.PostAsync(string.Format("http://{0}/api", bridgeIP),
                                     new StringContent(jsonObj));
                string returnString = "";

                try
                {
                    returnString = await response.Content.ReadAsStringAsync();
                    // Result will be
                    //"[{\"success\":{\"username\":\"brandnewdev\"}}]"
                    JArray result = JArray.Parse(returnString);
                    int successInt = 0;
                    if (result.Count == 2)
                        successInt = 1;
                    JToken success = result[successInt];
                    JToken username = success["success"];
                    JToken value = username["username"];
                    verifiedUser = value.ToString();
                    return verifiedUser;                        
                }
                catch (Exception ex)
                {
                    returnString = "Error: " + ex.Message;
                }

                return returnString;
            }
            catch (Exception ex)
            {
                return "Error: " + ex.Message;
            }
        }

        // Set the properties of a single light
        public async Task<string> SetLight(HueLight hl)
        {

            var lightState = new
            {
                on = hl.IsOn,
                hue = hl.Hue, 
                sat = hl.Saturation,
                bri = hl.Brightness 
            };

            var jsonObj = JsonConvert.SerializeObject(lightState);
            if (hl.Index == -1)
                return "No light index defined";

            var httpClient = new HttpClient();
            var lightUri = string.Format("http://{0}/api/{1}/lights/{2}/state", bridgeIP, userName, hl.Index);
            string returnString = "";
            try
            {
                var response = await httpClient.PutAsync(lightUri, new StringContent(jsonObj));
                returnString = await response.Content.ReadAsStringAsync();
            }
            catch (Exception ex)
            {
                returnString = ex.Message;
            }
            return returnString;
        }

        // Get the properties of a specific light
        public async Task<HueLight> GetLight(int index)
        {
            var httpClient = new HttpClient();
            var getLightUri = string.Format("http://{0}/api/{1}/lights/{2}", bridgeIP, userName, index);
            var response = await httpClient.GetAsync(getLightUri);
            
            try 
            {
                string resultString = await response.Content.ReadAsStringAsync();
                RawHueResult rhr = JsonConvert.DeserializeObject<RawHueResult>(resultString);
                HueLight returnLight = new HueLight(rhr.LightState, index);
                return returnLight;
            }
            catch(Exception ex)
            {
                return null;
            }

        }

        // Get the IP information for the Hue bridge
        //    *not tested*
        public async Task<HueSettings> GetBridgeIP()
        {
            try
            {
                var httpClient = new HttpClient();

                var response = await httpClient.GetAsync("http://www.meethue.com/api/nupnp");
                string returnString = "";

                try
                {
                    returnString = await response.Content.ReadAsStringAsync();
                    List<HueSettings> hueSet = JsonConvert.DeserializeObject<List<HueSettings>>(returnString);
                    if (hueSet != null && hueSet.Count == 1){
                        Hub = hueSet[0];
                        return Hub;

                    }
                    else
                        return null;

                    // Think up something for saving these settings
                }
                catch (Exception ex) { return null; }
            }
            catch (Exception ex) {
                return null;
            }
        }

        // Change the setup settings (ip and/or user settings)
        public async Task<string> UpdateSettings(string ip, string user)
        {
            bridgeIP = ip;
            userName = user;
            string returnString = await SetupUser();
            
            return returnString;
        }

    }
}
